package tigroids.timer;

import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;

import tigroids.timer.SingleTimer.State;
import android.app.Service;
import android.content.Intent;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
public class TimerService extends Service {
	static final int MESSAGE_WHAT_TICK_BEFORE_ELAPSED = 1;
	static final int MESSAGE_WHAT_STOP_RINGING = 2;
	static final int MESSAGE_WHAT_START_RINGING = 3;
	static final int MESSAGE_WHAT_TICK_AFTER_ELAPSED = 4;
	static final int INTENT_START_COMMAND_TIMER_START = 1001;
	static final int INTENT_START_COMMAND_TIMER_PAUSE = 1002;
	static final int INTENT_START_COMMAND_TIMER_RESUME = 1003;
	static final int INTENT_START_COMMAND_TIMER_CANCEL = 1004;

	private HashMap<Integer, CountDownTimer> runningCountdownTimers = new HashMap<Integer, CountDownTimer>();
	private HashMap<Integer, Timer> runningAfterElapsedTimers = new HashMap<Integer, Timer>();

	public TimerApplication getTimerApplication() {
		return (TimerApplication) super.getApplication();
	}

	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}
	
	
	
	protected void replaceAfterElapsedTimer(int timerId, Timer afterElapsedTimer) {
		Timer existingTimer = runningAfterElapsedTimers.get(timerId);
		if(existingTimer != null) {
			existingTimer.cancel();
		}
		runningAfterElapsedTimers.put(timerId, afterElapsedTimer);
	}
	

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		int command = intent.getExtras().getInt(TimerApplication.parameterNameCommand);
		final int timerId = (Integer) intent.getExtras().get(TimerApplication.parameterNameTimerToEdit);
		final SingleTimer timer = getTimerApplication().getTimer(timerId);
		
		switch (command) {

		case INTENT_START_COMMAND_TIMER_START:
		case INTENT_START_COMMAND_TIMER_RESUME:
			CountDownTimer cdt = new CountDownTimer(timer.getMillisecondsLeft(), 1000) {
				@Override
				public void onTick(long millisUntilFinished) {
					Message msg = Message.obtain(null, MESSAGE_WHAT_TICK_BEFORE_ELAPSED, timerId, (int) millisUntilFinished);
					timer.setMillisecondsLeft(millisUntilFinished);
					try {
						getTimerApplication().messenger.send(msg);
					} catch (RemoteException e) {
						throw new RuntimeException(e);
					}
				}

				@Override
				public void onFinish() {
					Message msg = Message.obtain(null, MESSAGE_WHAT_START_RINGING, timerId, 0);
					timer.setMillisecondsLeft(0);
					try {
						getTimerApplication().messenger.send(msg);
					} catch (RemoteException e) {
						throw new RuntimeException(e);
					}
					Timer afterElapsedTimer = new Timer(true);
					AfterElapsedTimerTask afterElapsedTimerTask = new AfterElapsedTimerTask(timer.getDuration().getDurationInmillis(), timerId, afterElapsedTimer);
					afterElapsedTimer.scheduleAtFixedRate(afterElapsedTimerTask, 0, 1000);
					
					replaceAfterElapsedTimer(timerId, afterElapsedTimer);
				}
			};

			// check for error -- whether we start already running timer
			if (runningCountdownTimers.containsKey(timerId)) {
				CountDownTimer tExisting = runningCountdownTimers.get(timerId);
				tExisting.cancel();
				runningCountdownTimers.remove(timerId);
			}
			runningCountdownTimers.put(timerId, cdt);
			cdt.start();
			break;

		case INTENT_START_COMMAND_TIMER_PAUSE:
		case INTENT_START_COMMAND_TIMER_CANCEL:
			if (timer.getCurrentState() != State.PAUSED && timer.getCurrentState() != State.INACTIVE) {
				Log.e(TimerApplication.logAppId, "Pausing or canceling a non-running timer");
			}
			CountDownTimer t = runningCountdownTimers.remove(timerId);
			if (t != null) {
				t.cancel();
			}
			
			replaceAfterElapsedTimer(timer.getId(), null);

			break;

		default:
			Log.e(TimerApplication.logAppId,
					"Incorrect value for the service start command in onStartCommand");
		}

		return super.onStartCommand(intent, flags, startId);
	}
	
	




	class AfterElapsedTimerTask extends TimerTask {
		long durationInMillis = 0;
		int elapsedMillis = 0;
		int timerId = 0;
		Timer timer = null;
		boolean isRinging = true;
		
		public AfterElapsedTimerTask(long d, int tid, Timer afterElapsedTimer) {
			durationInMillis = d;
			timerId = tid;
			timer = afterElapsedTimer;
		}

		@Override
		public void run() {
			Message msg = Message.obtain(null, MESSAGE_WHAT_TICK_AFTER_ELAPSED, timerId, (int) elapsedMillis);
			try {
				getTimerApplication().messenger.send(msg);
			} catch (RemoteException e) {
				throw new RuntimeException(e);
			}
			elapsedMillis += 1000;
			
			if(durationInMillis > 0 && elapsedMillis > durationInMillis && isRinging) {
        		msg = Message.obtain(null, TimerService.MESSAGE_WHAT_STOP_RINGING, timerId, 0);
				try {
					getTimerApplication().messenger.send(msg);
	        		isRinging = false;
				} catch (RemoteException e) {
					throw new RuntimeException(e);
				}
            }
		}
	}
	
	
	
	

}
